package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.PageUtil;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.itheima.commons.util.Constants;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.VideoApi;
import com.tanhua.dubbo.api.VideoCommentApi;
import com.tanhua.model.vo.*;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.enums.VideoType;
import com.tanhua.model.mongo.Video;
import com.tanhua.model.mongo.VideoComment;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class SmallVideosService {
    @Autowired
    private OssTemplate ossTemplate;
    @Autowired
    private FastFileStorageClient fastFileStorageClient;
    @Autowired
    private FdfsWebServer webServer;
    @DubboReference
    private VideoApi videoApi;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @DubboReference
    private UserInfoApi userInfoApi;
    @DubboReference
    private VideoCommentApi videoCommentApi;

    /**
     * 发布视频
     *
     * @param videoThumbnail 图片
     * @param videoFile      视频
     */
    public void saveVideos(MultipartFile videoThumbnail, MultipartFile videoFile) throws IOException {
        if (videoThumbnail.isEmpty() || videoFile.isEmpty()) {
            throw new BusinessException(ErrorResult.error());
        }
        //1、将视频上传到FastDFS,获取访问URL
        String filename = videoFile.getOriginalFilename();
        filename = filename.substring(filename.lastIndexOf(".") + 1);
        StorePath storePath = fastFileStorageClient.uploadFile(videoFile.getInputStream(), videoFile.getSize(), filename, null);
        String videoUrl = webServer.getWebServerUrl() + storePath.getFullPath();
        //2.将图片上传到阿里云
        String upload = ossTemplate.upload(videoThumbnail.getOriginalFilename(), videoThumbnail.getInputStream());
        //构建video对象，调用API保存到数据库
        Video video = new Video();
        video.setUserId(UserHolder.getUserId());
        video.setPicUrl(upload);
        video.setVideoUrl(videoUrl);
        String videoId = videoApi.save(video);
        if (StringUtils.isEmpty(videoId)) {
            throw new BusinessException(ErrorResult.error());
        }
    }

    //分页查询视频列表
    public PageResult queryVideoList(Integer page, Integer pagesize) {
        //1、查询redis数据
        String key = Constants.VIDEOS_RECOMMEND + UserHolder.getUserId();
        String redisValue = redisTemplate.opsForValue().get(key);
        List<Video> list = new ArrayList<>();
        //2、判断redis数据是否存在，判断redis中数据是否满足本次分页条数
        int redisPages = 0;
        if (!StringUtils.isEmpty(redisValue)) {
            //3、如果redis数据存在，根据VID查询数据
            String[] values = redisValue.split(",");
            //判断当前页的起始条数是否小于数组总数
            if ((page - 1) * pagesize < values.length) {
                List<Long> vids = Arrays.stream(values).skip((page - 1) * pagesize).limit(pagesize)
                        .map((e) -> Long.valueOf(e)).collect(Collectors.toList());
                //5、调用API根据PID数组查询动态数据
                list = videoApi.findVideosByVids(vids);
            }
            redisPages = PageUtil.totalPage(values.length, pagesize);
        }
        //4、如果redis数据不存在，分页查询视频数据
        if (list.isEmpty()) {
            //page的计算规则，  传入的页码  -- redis查询的总页数
            list = videoApi.queryVideoList(page - redisPages, pagesize);
        }
        //5、提取视频列表中所有的用户id
        List<Long> userId = CollUtil.getFieldValues(list, "userId", Long.class);
        //6、查询用户信息
        ArrayList<VideoVo> vos = new ArrayList<>();
        Map<Long, UserInfo> mp = userInfoApi.findByIds(userId, null);
        for (Video video : list) {
            UserInfo userInfo = mp.get(video.getUserId());
            if (userInfo != null) {
                VideoVo vo = VideoVo.init(userInfo, video);
                String key1 = Constants.VIDEOS_INTERACT_KEY + video.getId().toHexString();
                String hashKey = Constants.VIDEO_LIKE_HASHKEY + UserHolder.getUserId();
                if (redisTemplate.opsForHash().hasKey(key1, hashKey)) {
                    vo.setHasLiked(1);
                }
                if (redisTemplate.opsForHash().hasKey(Constants.USER_LIKE_KEY + UserHolder.getUserId(),video.getUserId().toString())){
                    vo.setHasFocus(1);
                }
                vos.add(vo);
            }
        }
        //7、构建返回值
        return new PageResult(page, pagesize, 0, vos);
    }

    //对视频点赞
    public Integer VideoLikes(String videoId) {
        //先判断用户是否点赞，查询VideoComment表
        Boolean hasVideo = videoCommentApi.hasVideo(videoId, UserHolder.getUserId(), VideoType.LIKE);
        //如果已经点赞则抛出异常
        if (hasVideo) {
            throw new BusinessException(ErrorResult.likeError());
        }
        //没点赞则调用API保存到mongo表
        VideoComment videoComment = new VideoComment();
        videoComment.setVideoId(new ObjectId(videoId));
        videoComment.setVideoType(VideoType.LIKE.getType());
        videoComment.setUserId(UserHolder.getUserId());
        videoComment.setCreated(System.currentTimeMillis());
        Integer count = videoCommentApi.save(videoComment);
        //拼接redis的key，将用户的点赞状态存入redis
        String key = Constants.VIDEOS_INTERACT_KEY + videoId;
        String hashKey = Constants.VIDEO_LIKE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().put(key, hashKey, "1");
        return count;
    }

    //取消点赞
    public Integer VideodisLikes(String videoId) {
        Boolean hasVideo = videoCommentApi.hasVideo(videoId, UserHolder.getUserId(), VideoType.LIKE);
        //如果已经点赞则抛出异常
        if (!hasVideo) {
            throw new BusinessException(ErrorResult.disLikeError());
        }
        //调用API删除videoComment表中得数据
        VideoComment videoComment = new VideoComment();
        videoComment.setVideoId(new ObjectId(videoId));
        videoComment.setUserId(UserHolder.getUserId());
        videoComment.setVideoType(VideoType.LIKE.getType());
        Integer count = videoCommentApi.delete(videoComment);
        //调用redis删除点赞状态
        String key = Constants.VIDEOS_INTERACT_KEY + videoId;
        String hashKey = Constants.VIDEO_LIKE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().delete(key, hashKey, "1");
        return count;
    }

    //保存评论
    public void saveComments(String videoId, String comment) {
        //构建数据保存到数据库
        VideoComment videoComment = new VideoComment();
        videoComment.setVideoId(new ObjectId(videoId));
        videoComment.setContent(comment);
        videoComment.setVideoType(VideoType.COMMENT.getType());
        videoComment.setUserId(UserHolder.getUserId());
        videoComment.setCreated(System.currentTimeMillis());
        videoComment.setCommentLike(new ArrayList<>());
        videoCommentApi.save(videoComment);
    }

    /**
     * 分页查询评论列表
     *
     * @param id       评论ID
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult queryVideoComment(String id, Integer page, Integer pagesize) {
        //查询出评论
        List<VideoComment> list = videoCommentApi.findComments(id, page, pagesize, VideoType.COMMENT.getType());
        if (CollUtil.isEmpty(list)){
            return new PageResult(page,pagesize,0, null);
        }
        //提取评论中评论人得ID
        List<Long> userId = CollUtil.getFieldValues(list, "userId", Long.class);
        //根据UserInfoApi查询所有人得资料
        ArrayList<VideoCommentVo> vos = new ArrayList<>();
        Map<Long, UserInfo> map = userInfoApi.findByIds(userId,null);
        for (VideoComment videoComment : list) {
            UserInfo userInfo = map.get(videoComment.getUserId());
            if (userInfo!=null){
                VideoCommentVo videoCommentVo = VideoCommentVo.init(userInfo, videoComment);
                //判断是否点赞，点赞则设置为1
                String key = Constants.MOVEMENTS_INTERACT_KEY + videoComment.getId().toHexString();
                String hashKey = Constants.COMMENT_LIKE_HASHKEY + UserHolder.getUserId();
                if (redisTemplate.opsForHash().hasKey(key,hashKey)){
                    videoCommentVo.setHasLiked(1);
                }
                vos.add(videoCommentVo);
            }
        }
        PageResult pageResult = new PageResult(page, pagesize, 0, vos);
        return pageResult;
    }


    //评论点赞
    public Integer Commentlike(String id) {
        //获取评论列表，获取到点赞人列表,循环列表判断是否点赞
        //CommentLike是点赞人列表
        VideoComment videoComment = videoCommentApi.findByIdComment(id,UserHolder.getUserId());
        List<Long> commentLike = videoComment.getCommentLike();
        for (Long aLong : commentLike) {
            if (aLong.equals(UserHolder.getUserId())){
                throw new BusinessException(ErrorResult.likeError());
            }
        }
        Integer likeCount = videoComment.getLikeCount();
        String key = Constants.VIDEOS_INTERACT_KEY + id;
        String hashKey = Constants.COMMENT_LIKE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().put(key,hashKey,"1");
        return likeCount;
    }
    //评论取消点赞
    public Integer CommentDislike(String id) {
        VideoComment videoComment = videoCommentApi.findByIdComment1(id,UserHolder.getUserId());
        //获取评论列表，获取到点赞人列表,循环列表判断是否点赞
        List<Long> commentLike = videoComment.getCommentLike();
        for (Long aLong : commentLike) {
            if (!aLong.equals(UserHolder.getUserId())){
                throw new BusinessException(ErrorResult.disLikeError());
            }
        }
        //获得评论点赞数，返回
        Integer likeCount = videoComment.getLikeCount();
        String key = Constants.VIDEOS_INTERACT_KEY + id;
        String hashKey = Constants.COMMENT_LIKE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().delete(key,hashKey);
        return likeCount;
    }
}
